package vip.xiaonuo.modular.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.java.Log;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import vip.xiaonuo.core.dbs.CurrentDataSourceContext;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.HttpServletUtil;
import vip.xiaonuo.modular.business.entity.PointAnalysisVo;
import vip.xiaonuo.modular.business.param.BiUserIndexType.QueryParam;
import vip.xiaonuo.modular.business.param.PointAnalysisParam;
import vip.xiaonuo.modular.business.service.IndexTypeManageService;
import vip.xiaonuo.modular.business.service.PointAnalysisService;
import vip.xiaonuo.modular.cache.BaseDataRecordCache;
import vip.xiaonuo.modular.cache.IndustryWeightCache;
import vip.xiaonuo.modular.common.DistanceHelper;
import vip.xiaonuo.modular.common.GridColorUtils;
import vip.xiaonuo.modular.common.WdAnalysisConst;
import vip.xiaonuo.modular.entitys.UserIndexTree;
import vip.xiaonuo.modular.indextypeweight.entity.IndexTypeWeight;
import vip.xiaonuo.modular.indextypeweight.service.IndexTypeWeightService;
import vip.xiaonuo.modular.manage.biapplication.entity.BiApplication;
import vip.xiaonuo.modular.manage.biapplication.service.BiApplicationService;
import vip.xiaonuo.modular.manage.biindexdata.entity.BiIndexData;
import vip.xiaonuo.modular.manage.biindexdata.mapper.BiIndexDataMapper;
import vip.xiaonuo.modular.manage.biindexdata.param.BiIndexDataParam;
import vip.xiaonuo.modular.manage.biindexdata.service.BiIndexDataService;
import vip.xiaonuo.modular.manage.biindextype.entity.BiIndexType;
import vip.xiaonuo.modular.manage.biindextype.service.BiIndexTypeService;
import vip.xiaonuo.modular.manage.bioperateddata.entity.BiOperatedData;
import vip.xiaonuo.modular.manage.bioperateddata.service.BiOperatedDataService;
import vip.xiaonuo.modular.manage.poidata.entity.BiPoiData;
import vip.xiaonuo.modular.manage.poidata.mapper.BiPoiDataMapper;
import vip.xiaonuo.modular.manage.storeorder.entity.BiStoreOrder;
import vip.xiaonuo.modular.manage.storeorder.mapper.BiStoreOrderMapper;
import vip.xiaonuo.modular.manage.storeorder.param.BiStoreOrderParam;
import vip.xiaonuo.modular.pointrepository.service.PointRepositoryService;
import vip.xiaonuo.sys.modular.area.entity.SysArea;
import vip.xiaonuo.sys.modular.area.service.SysAreaService;
import vip.xiaonuo.sys.modular.org.entity.SysOrg;
import vip.xiaonuo.sys.modular.org.service.SysOrgService;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: liu
 * @Date:2022/10/20
 */
@Service
@Log
public class PointAnalysisServiceImpl implements PointAnalysisService {
    @Resource
    private PointRepositoryService pointRepositoryService;

    @Resource
    private BiIndexTypeService biIndexTypeService;

    @Resource
    private BiIndexDataMapper biIndexDataMapper;

    @Resource
    private BiStoreOrderMapper biStoreOrderMapper;

    @Resource
    private BaseDataRecordCache baseDataRecordCache;

    @Resource
    private IndustryWeightCache industryWeightCache;


    @Resource
    private IndexTypeWeightService indexTypeWeightService;

    @Resource
    private SysOrgService sysOrgService;

    @Resource
    private BiOperatedDataService biOperatedDataService;
    @Resource
    private SysAreaService sysAreaService;

    @Resource
    private BiIndexDataService biIndexDataService;

    @Resource
    private IndexTypeManageService indexTypeManageService;

    @Resource
    private BiPoiDataMapper biPoiDataMapper;

    @Resource
    private BiApplicationService biApplicationService;

    /**
     * 地址分析
     * @param param
     * @return
     */
    @Override
    public JSONObject findPoint(PointAnalysisParam param) {
        if (param.getDistance() == null || param.getThemeId() == null) {
            throw new ServiceException(9, "主题和半径参数不能为空");
        }
        HttpServletRequest request = HttpServletUtil.getRequest();
        JSONObject industryWeight = param.getIndustryWeight();
        if (industryWeight != null && industryWeight.size()>0) {
            request.getSession().setAttribute("INDUSTRY_"+param.getThemeId(), industryWeight);
            Set<String> indexes = industryWeight.keySet();
            List<Long> indexList = indexes.stream().map(el -> Long.parseLong(el)).collect(Collectors.toList());
            param.setIndexList(indexList);
        }
        JSONObject result = new JSONObject();
        List<Long> pointIds = param.getPointIds();
        List list = new ArrayList();

        if(param.getLng() !=null && param.getLat()!= null){
            String location = param.getLng().toPlainString()+","+param.getLat().toPlainString();
            JSONObject point = new JSONObject();
            point.put("name", requestAmapRegeocodeAddress(location));
            point.put("lng", param.getLng());
            point.put("lat", param.getLat());
            list.add(point);
        }else if (CollectionUtil.isNotEmpty(pointIds)) {
            list = pointRepositoryService.listByIds(pointIds);
        } else if (StringUtils.hasText(param.getAddress())) {
            String city = param.getCity();
            if (StringUtils.isEmpty(city)) {
                city = "武汉市";
            }
            list = this.requestAmapGeocode(city, param.getAddress());
        }else{
            throw new ServiceException(9, "参数错误");
        }
        long startTime = System.currentTimeMillis();
        log.info("计算点位数量：" + list.size());
        JSONArray rows = new JSONArray();
        List<IndexTypeWeight> weightList = indexTypeWeightService.list(new LambdaQueryWrapper<IndexTypeWeight>().select(IndexTypeWeight::getTypeId));
        List<Long> typeList = weightList.stream().map(e->e.getTypeId()).distinct().collect(Collectors.toList());
        log.info("可计算的指标：" + CollectionUtil.join(typeList,","));
        List<Long> indexList = param.getIndexList();
        if (CollectionUtil.isNotEmpty(indexList)) {
            log.info("用户筛选后的指标：" + CollectionUtil.join(indexList,","));
            List<Long> typeListNew = new ArrayList<>();
            for (Long l : indexList) {
                if (typeList.contains(l)) {
                    typeListNew.add(l);
                }
            }
            typeList = typeListNew;
            log.info("用户筛选后的指标数量：" + typeList.size());
        }
        JSONObject industryWeightCacheMap = getIndustryWeightCacheMap(param.getThemeId(),true);
        // 循环查询结果，最多返回10条记录
        for (int i=0;i<list.size();i++) {
            JSONObject element = null;
            Object o = list.get(i);
            // 名称：武汉大学
            Object name = BeanUtil.getProperty(o, "name");
            long loopTime = System.currentTimeMillis();
            log.info("准备处理分析地址："+name);
            // 分数：83.00
            BigDecimal lng = (BigDecimal)BeanUtil.getProperty(o, "lng");
            BigDecimal lat = (BigDecimal)BeanUtil.getProperty(o, "lat");
            String key = MD5.create().digestHex(lng.toString()+lat+param.getThemeId()+param.getDistance()+industryWeightCacheMap.toJSONString());
            if (CollectionUtil.isNotEmpty(typeList)) {
                String join = CollectionUtil.join(typeList, ",");
                key += join;
            }
            JSONObject cacheObject = baseDataRecordCache.get(key);
            if (cacheObject != null) {
                element = cacheObject;
            }else{
                element = new JSONObject();
                element.put("name", name);
                element.put("lng", lng);
                element.put("lat", lat);
                JSONObject calcScore = this.calcAllIndexScore(typeList,lng, lat, param);
                element.put("seq",i+1);
                element.put("score",calcScore.getBigDecimal("score"));
                // 选址评分雷达图： 住宅、人口等 指标得分
                JSONArray indexScoreList = calcScore.getJSONArray("indexScoreList");
                if (indexScoreList != null && indexScoreList.size() > 0) {
                    JSONObject maxScoreObject = (JSONObject) indexScoreList.get(0);
                    for (Object obj : indexScoreList) {
                        JSONObject el = (JSONObject) obj;
                        if(el.getBigDecimal("value").compareTo(maxScoreObject.getBigDecimal("value"))>0){
                            maxScoreObject = el;
                        }
                    }
                    element.put("tag", maxScoreObject.getString("name")+"分值高");
                }

                element.put("indexScoreList", indexScoreList);
                //指标总数
                element.put("indexSumList",calcScore.getJSONArray("indexSumList"));
                // 同类主题“近一年”真实成交数据
                log.info("计算同类主题近一年真实成交数据");
                JSONArray themeStoreOrderSum = queryThemeStoreOrderSum(param.getThemeId(),lng,lat,param.getDistance());
                element.put("themeDataSum",themeStoreOrderSum );
                element.put("themeId", param.getThemeId());
                baseDataRecordCache.put(key, element);
            }
            log.info("处理分析地址完成："+name + ",用时："+(System.currentTimeMillis() - loopTime));
            rows.add(element);
            if(i>=10){
                break;
            }
        }
        log.info("全部处理完成，点位数量"+rows.size() + ",用时："+(System.currentTimeMillis() - startTime));
        result.put("rows", rows);
        // 保存到session会话中，可以提供对比操作
        request.getSession().setAttribute("FIND_POINT",rows);
        return result;
    }

    /**
     * 同类主题“近一年”真实成交数据
     * 计算一个点附近N公里的店铺订单信息
     * @return
     */
    private JSONArray queryThemeStoreOrderSum(Long themeId,BigDecimal lng,BigDecimal lat,Integer distance) {
        JSONArray result = new JSONArray();
        List<SysOrg> orgList = sysOrgService.list(new LambdaQueryWrapper<SysOrg>().eq(SysOrg::getIndustryId, themeId));
        HashMap<String, String> orgNameMap = new HashMap<>();
        for (SysOrg s : orgList) {
            orgNameMap.put(s.getCode(), s.getName());
        }
        List<String> orgCodeList = orgList.stream().map(e -> e.getCode()).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(orgCodeList)) {
            return result;
        }
        // 根据点位和半径 筛选周围的店铺信息
        String[] nearbyDistance = DistanceHelper.getNearbyDistance(lng, lat, distance);
        LambdaQueryWrapper<BiOperatedData> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.in(BiOperatedData::getOrgCode, orgCodeList);
        wrapper1.between(BiOperatedData::getLng,nearbyDistance[0],nearbyDistance[1]);
        wrapper1.between(BiOperatedData::getLat,nearbyDistance[2],nearbyDistance[3]);
        List<BiOperatedData> storeList = biOperatedDataService.list(wrapper1);
        List<BiOperatedData> storeListFilter = new ArrayList<>();
        for (BiOperatedData b : storeList) {
            //判断店铺的位置半径是否符合N公里条件
            double d = DistanceHelper.getDistince(DistanceHelper.parseDouble(b.getLng()),DistanceHelper.parseDouble(b.getLat()),
                    lng.doubleValue(),lat.doubleValue());
            if(d > distance){
                continue;
            }
            //增加店铺图标
            b.setImageUrl(getStoreImageUrl(b.getOrgCode()));
            storeListFilter.add(b);
        }
        List<String> storeCodeList = storeListFilter.stream().map(e -> e.getStoreId()).collect(Collectors.toList());
        HashMap<String, Integer> countStoreNumMap = new HashMap<>();
        for (BiOperatedData d : storeListFilter) {
            Integer integer = countStoreNumMap.get(d.getOrgCode());
            if (integer == null) {
                integer = 1;
            }else{
                integer++;
            }
            countStoreNumMap.put(d.getOrgCode(), integer);
        }

        BiStoreOrderParam param1 = new BiStoreOrderParam();
        param1.setStoreCodeList(storeCodeList);
        CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
        List<Map<String, Long>> maps = biStoreOrderMapper.groupByOrgCode(param1);
        CurrentDataSourceContext.clearDataSourceType();

        if (CollectionUtil.isNotEmpty(maps)) {
            for (Map<String, Long> m : maps) {
                Integer countStoreNum = countStoreNumMap.get(m.get("org_code"));
                if (countStoreNum == null) {
                    continue;
                }
                JSONObject element = new JSONObject();
                element.put("name", orgNameMap.get(m.get("org_code")));
                element.put("totalCount", m.get("total_count"));
                element.put("totalAmount", m.get("total_amount"));
                element.put("countStoreNum", countStoreNum);
                element.put("storeList", storeListFilter);
                result.add(element);
            }
        }
        return result;
    }

    /**
     * 根据店铺类型获取图标字符串
     * @param orgCode
     * @return
     */
    private String getStoreImageUrl(String orgCode) {
        JSONObject cacheObject = baseDataRecordCache.get("getStoreImageUrl");
        if (cacheObject == null) {
            cacheObject = new JSONObject();
            List<BiApplication> list = biApplicationService.list();
            if (CollectionUtil.isNotEmpty(list)) {
                for (BiApplication b : list) {
                    cacheObject.put(b.getOrgCode(), b.getImageUrl());
                }
            }
            baseDataRecordCache.put("getStoreImageUrl", cacheObject,10*60L);
        }

        return cacheObject.getString(orgCode);
    }

    /**
     *查询同类型“主题”真实成交数据
     * @param param
     * @return
     */
    @Override
    public PageResult<BiStoreOrder> queryThemeOrderPage(PointAnalysisParam param) {
        Long themeId = param.getThemeId();
        if (themeId == null) {
            throw new ServiceException(9, "主题编号不能为空");
        }
        if (param.getDistance() == null || param.getLng()==null||param.getLat() == null) {
            throw new ServiceException(9, "经纬度和半径不能为空");
        }
        PageResult<BiStoreOrder> result = new PageResult<>();
        List<SysOrg> orgList = sysOrgService.list(new LambdaQueryWrapper<SysOrg>().eq(SysOrg::getIndustryId, themeId));
        List<String> orgCodeList = orgList.stream().map(e -> e.getCode()).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(orgCodeList)) {
            return result;
        }

        // 根据点位和半径 筛选周围的店铺信息
        String[] nearbyDistance = DistanceHelper.getNearbyDistance(param.getLng(), param.getLat(), param.getDistance());
        LambdaQueryWrapper<BiOperatedData> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.in(BiOperatedData::getOrgCode, orgCodeList);
        wrapper1.between(BiOperatedData::getLng,nearbyDistance[0],nearbyDistance[1]);
        wrapper1.between(BiOperatedData::getLat,nearbyDistance[2],nearbyDistance[3]);
        List<BiOperatedData> storeList = biOperatedDataService.list(wrapper1);
        List<String> storeCodeList = storeList.stream().map(e -> e.getStoreId()).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(storeCodeList)) {
            return new PageResult<>(new Page<>());
        }

        HashMap<String, Object> param1 = new HashMap<>();
        param1.put("storeCodeList", storeCodeList);
        if (StringUtils.hasText(param.getStoreName())) {
            param1.put("storeName","%"+param.getStoreName()+"%");
        }
        if (param.getStartDate()!=null && param.getEndDate()!=null) {
            param1.put("startDate",param.getStartDate());
            param1.put("endDate",param.getEndDate());
        }
        CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
        Page biStoreOrderPage = biStoreOrderMapper.selectPageGroupByName(PageFactory.defaultPage(), param1);
        List<BiStoreOrder> records = biStoreOrderPage.getRecords();
        CurrentDataSourceContext.clearDataSourceType();

        List<JSONObject> newRecords = new ArrayList<>();
        for (BiStoreOrder b : records) {
            JSONObject el = new JSONObject();
            el.put("storeName", b.getStoreName());
            el.put("tradeAmount", b.getTradeAmount());
            el.put("tradeCount", b.getRefundAmount().setScale(0,4));
            el.put("address", b.getStoreName());
            LambdaQueryWrapper<BiOperatedData> w = new LambdaQueryWrapper<>();
            w.eq(BiOperatedData::getStoreName, b.getStoreName());
            w.last(" limit 1 ");
            BiOperatedData one = biOperatedDataService.getOne(w);
            if (one != null) {
                el.put("address", one.getAddress());
            }
            newRecords.add(el);
        }
        biStoreOrderPage.setRecords(newRecords);
        result = new PageResult<>(biStoreOrderPage);
        return result;
    }

    private ArrayList<PointAnalysisVo> requestAmapGeocode(String city, String address) {
        ArrayList<PointAnalysisVo> list = new ArrayList<>();
        // 调用高德api接口将地址转码成经纬度
        String url = WdAnalysisConst.AMAP_GEOCODE_URL;
        Map<String, Object> p = new HashMap<>();
        p.put("key", WdAnalysisConst.AMAP_KEY);
        p.put("address", address);
        p.put("city", city);
        String s = HttpUtil.get(url, p);
        JSONArray geocodes = JSONObject.parseObject(s).getJSONArray("geocodes");
        if (geocodes == null) {
            return list;
        }
        geocodes.forEach(e -> {
            JSONObject obj = (JSONObject)e;
            PointAnalysisVo vo = new PointAnalysisVo();
            String district = obj.getString("district");
            String formattedAddress = obj.getString("formatted_address");
            String location = obj.getString("location");
            String name = formattedAddress;
            if (formattedAddress.contains(district)) {
                name = formattedAddress.split(district)[1];
            }
            vo.setName(name);
            vo.setAddress(formattedAddress);
            vo.setLng(new BigDecimal(location.split(",")[0]));
            vo.setLat(new BigDecimal(location.split(",")[1]));
            list.add(vo);
        });
        return list;
    }

    private String requestAmapRegeocodeAddress(String location) {
        String url = WdAnalysisConst.AMAP_REGEOCODE_URL;
        Map<String, Object> p = new HashMap<>();
        p.put("key", WdAnalysisConst.AMAP_KEY);
        p.put("location", location);
        p.put("radius", 1000);
        String s = HttpUtil.get(url, p);
        JSONObject object = JSONObject.parseObject(s).getJSONObject("regeocode");
        return object.getString("formatted_address");
    }

    public JSONObject calcAllIndexScore(List<Long> typeList ,BigDecimal lng,BigDecimal lat, PointAnalysisParam param) {
        JSONObject result = new JSONObject();
        if (CollectionUtil.isEmpty(typeList)) {
            return result;
        }
        List<BiIndexType> list = biIndexTypeService.findByIds(typeList);
        double totalScore = 0;
        double totalSum = 0;
        int count = 0;
        JSONArray indexScoreList = new JSONArray();
        JSONArray indexSumList = new JSONArray();
        HashMap<String, BigDecimal> scoreMap = new HashMap<>();
        for (BiIndexType type : list) {
            JSONObject object = this.statisticsIndex(type,lng,lat,param);
            BigDecimal score = object.getBigDecimal("score");
            BigDecimal sum = object.getBigDecimal("sum");
            if (sum.compareTo(BigDecimal.ZERO) == 0) {
                continue;
            }
            totalScore += score.doubleValue();
            totalSum += sum.doubleValue();
            JSONObject scoreObject = new JSONObject();
            scoreObject.put("id", type.getId());
            scoreObject.put("name", type.getName());
            scoreObject.put("value",score);
            indexScoreList.add(scoreObject);
            scoreMap.put(type.getName(), score);
            JSONObject sumObject = new JSONObject();
            sumObject.put("name", type.getName());
            sumObject.put("value",sum);
            indexSumList.add(sumObject);
            count ++;
        }
        if (count == 0) {
            result.put("score", BigDecimal.ZERO);
            result.put("indexScoreList", indexScoreList);
            result.put("indexSumList", indexSumList);
        }else{
            result.put("score", calcScoreByIndustryWeight(indexScoreList,param.getThemeId()));
            result.put("indexSumList", indexSumList);
            // 特色处理，查询详细的时候指标不分组，其他情况按照指标的大类分组
            if (!"DETAIL_REPORT".equals(param.getColor())) {
                JSONArray groupedScoreList = this.groupIndexScore(indexScoreList);
                result.put("indexScoreList", groupedScoreList);
            }else{
                result.put("indexScoreList", indexScoreList);
            }
        }

        return result;
    }

    /**
     * 根据每个指标，每个行业对应的权重计算
     * @param indexScoreList
     * @return
     */
    private BigDecimal calcScoreByIndustryWeight(JSONArray indexScoreList,Long industryId){
        JSONObject map = getIndustryWeightCacheMap(industryId,true);
        BigDecimal score = BigDecimal.ZERO;
        for (Object s : indexScoreList) {
            JSONObject jsonObject = (JSONObject) s;
            BigDecimal weightValue = map.getBigDecimal(String.valueOf(jsonObject.get("id")));
            if(weightValue != null){
                BigDecimal value = jsonObject.getBigDecimal("value");
                score = score.add(value.multiply(weightValue));
            }
        }
        return score;
    }

    public JSONObject getIndustryWeightCacheMap(Long industryId,boolean fromSession) {
        //根据用户选择的主题，获取该主题下的各个指标权重
        //（首先从session会话中获取，如果不存在则查询数据库）
        HttpSession session = HttpServletUtil.getRequest().getSession();
        if (fromSession) {
            JSONObject obj = (JSONObject)session.getAttribute("INDUSTRY_" + industryId);
            if (obj != null && obj.size()>0) {
                return (JSONObject) obj;
            }
        }
        JSONObject map = industryWeightCache.get(String.valueOf(industryId));
        if (map == null) {
            map = new JSONObject();
            List<IndexTypeWeight> list = indexTypeWeightService.lambdaQuery().eq(IndexTypeWeight::getIndustryId, industryId).list();
            if (CollectionUtil.isNotEmpty(list)) {
                for (IndexTypeWeight w : list) {
                    map.put(String.valueOf(w.getTypeId()), w.getWeightVal());
                }
            }
            industryWeightCache.put(String.valueOf(industryId),map);
        }
        session.setAttribute("Industry" + industryId,map);
        return map;
    }

    /**
     * 统计点位周围N公里的指标，并根据最大值和最小值计算分数
     * @param type
     * @param lng
     * @param lat
     * @param param
     * @return
     */
    private JSONObject statisticsIndex(BiIndexType type,BigDecimal lng,BigDecimal lat, PointAnalysisParam param){
        log.info("计算单个指标分值:"+type.getName());
        JSONObject result = new JSONObject();
        if (type.getMaxValue() == null || type.getMinValue() == null) {
            // 计算并更新该指标的最大值最小值
            log.info("更新该指标的最大值最小值:"+type.getName());
            biIndexTypeService.updateMaxMinValue(type);
        }
        double maxValue = type.getMaxValue().doubleValue();
        double minValue = type.getMinValue().doubleValue();
        // 指标最大值为0，跳过处理
        if (type.getMaxValue().equals(BigDecimal.ZERO)) {
            result.put("score", BigDecimal.ZERO);
            result.put("sum", BigDecimal.ZERO);
            return result;
        }
        //查询半径N公里内的指标
        int distance = param.getDistance();
        String[] points = DistanceHelper.getNearbyDistance(lng, lat, distance);
        BiIndexDataParam biIndexDataParam = new BiIndexDataParam();
        biIndexDataParam.setLng1(points[0]);
        biIndexDataParam.setLng2(points[1]);
        biIndexDataParam.setLat1(points[2]);
        biIndexDataParam.setLat2(points[3]);
        biIndexDataParam.setTypeId(type.getId());
        biIndexDataParam.setYear(String.valueOf(DateUtil.year(new Date())));
        CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
        List<BiIndexData> biIndexData = biIndexDataMapper.selectListCustom(biIndexDataParam);
        CurrentDataSourceContext.clearDataSourceType();

        List<BiIndexData> biIndexFilterList = new ArrayList<>();
        for (BiIndexData b : biIndexData) {
            double value = Double.parseDouble(b.getValue());
            if (value == 0) {
                continue;
            }
            //判断店铺的位置半径是否符合5公里条件
            double d = DistanceHelper.getDistince(DistanceHelper.parseDouble(b.getLng()),DistanceHelper.parseDouble(b.getLat()),
                    lng.doubleValue(),lat.doubleValue());
            if(d > distance){
                continue;
            }
            biIndexFilterList.add(b);
        }
        if (CollectionUtil.isEmpty(biIndexFilterList)) {
            result.put("score", BigDecimal.ZERO);
            result.put("sum", BigDecimal.ZERO);
            return result;
        }
        //最大值和最小值区间等额划分成10个小区间，计算分数
        if(minValue < 0){
            minValue = 0;
        }
        final double min = minValue;
        double p = (maxValue-minValue)/10;
        double[] array = biIndexFilterList.stream().mapToDouble(b -> Double.parseDouble(b.getValue())).toArray();
        double sum = Arrays.stream(array).sum();
        double score = Arrays.stream(array).map(v -> ((v - min) / p ) * 10).average().getAsDouble();

        result.put("score", new BigDecimal(score).setScale(0, BigDecimal.ROUND_HALF_DOWN));
        result.put("sum", new BigDecimal(sum).setScale(3, BigDecimal.ROUND_HALF_UP));
        log.info("分值计算结果:"+result.toJSONString());
        return result;
    }

    /**
     * 对比分析
     * @param param
     * @return
     */
    @Override
    public JSONObject comparePoint(PointAnalysisParam param) {
        List<Long> pointIds = param.getPointIds();
        if (pointIds == null || pointIds.size() != 2) {
            throw new ServiceException(9, "请传入两个点编号");
        }
        HttpServletRequest request = HttpServletUtil.getRequest();
        Object rows = request.getSession().getAttribute("FIND_POINT");
        if (rows == null) {
            throw new ServiceException(9, "请先点击开始分析后进行对比");
        }
        List points = null;
        if (rows instanceof JSONArray) {
            points = (JSONArray)rows;
        }else if(rows instanceof ArrayList){
            points = (ArrayList)rows;
        }


        JSONObject result = new JSONObject();
        ArrayList<JSONObject> array = new ArrayList<>();
        for (Object o : points) {
            JSONObject object = (JSONObject) o;
            if (pointIds.contains(object.getLong("seq"))) {
                array.add(object);
            }
        }
        JSONObject compareResult = new JSONObject();
        JSONArray indexScoreList1 = array.get(0).getJSONArray("indexScoreList");
        JSONArray indexScoreList2 = array.get(1).getJSONArray("indexScoreList");
        if (indexScoreList1 != null && indexScoreList1.size() > 0
                &&indexScoreList2 != null && indexScoreList2.size() > 0) {
            HashMap<String, BigDecimal> map1 = new HashMap<>();
            HashMap<String, BigDecimal> map2 = new HashMap<>();
            for (Object o : indexScoreList1) {
                JSONObject object = (JSONObject) o;
                map1.put(object.getString("name"),object.getBigDecimal("value"));
            }
            for (Object o : indexScoreList2) {
                JSONObject object = (JSONObject) o;
                map2.put(object.getString("name"),object.getBigDecimal("value"));
            }
            // 计算两个数字的比例
            Set<String> keySet = map1.keySet();
            final BigDecimal HUNDRED = new BigDecimal(100);
            for (String s : keySet) {
                BigDecimal v1 = map1.get(s);
                BigDecimal v2 = map2.get(s);
                if (v1 != null && v2 != null) {
                    BigDecimal sum = v1.add(v2);
                    JSONArray arr = new JSONArray();
                    BigDecimal n1 = v1.divide(sum,3,4).multiply(HUNDRED).setScale(0, BigDecimal.ROUND_HALF_UP);
                    arr.add(n1);
                    arr.add(HUNDRED.subtract(n1));
                    compareResult.put(s, arr);
                }
            }
        }
        ArrayList<JSONObject> pointList = new ArrayList<>();
        for (Object o : array) {
            JSONObject object = (JSONObject) o;
            JSONObject element = new JSONObject();
            element.put("name", object.get("name"));
            element.put("score", object.get("score"));
            element.put("seq", object.get("seq"));
            pointList.add(element);
        }
        result.put("pointList",pointList);
        result.put("compareResult", compareResult);
        return result;
    }

    @Override
    public JSONObject findArea(PointAnalysisParam param) {
        if (StringUtils.isEmpty(param.getThemeId())) {
            throw new ServiceException(9, "themeId字段不能为空");
        }
        HttpServletRequest request = HttpServletUtil.getRequest();
        JSONObject industryWeight = param.getIndustryWeight();
        if (industryWeight != null && industryWeight.size()>0) {
            request.getSession().setAttribute("INDUSTRY_"+param.getThemeId(), industryWeight);
            Set<String> indexes = industryWeight.keySet();
            List<Long> indexList = indexes.stream().map(el -> Long.parseLong(el)).collect(Collectors.toList());
            param.setIndexList(indexList);
        }
        String districtName = "武汉市";
        LambdaQueryWrapper<BiIndexData> w = new LambdaQueryWrapper<>();
        w.select(BiIndexData::getGrid,BiIndexData::getLng, BiIndexData::getLat, BiIndexData::getTypeId, BiIndexData::getValue, BiIndexData::getMultipolygon);
        BigDecimal lng1 = param.getLng1();
        BigDecimal lng2 = param.getLng2();
        BigDecimal lat1 = param.getLat1();
        BigDecimal lat2 = param.getLat2();
        if (lng1 != null && lat1 != null) {
            if(lng1.compareTo(lng2)>0){
                param.setLng1(lng2);
                param.setLng2(lng1);
            }
            if(lat1.compareTo(lat2)>0){
                param.setLat1(lat2);
                param.setLat2(lat1);
            }
            w.between(BiIndexData::getLat,param.getLat1().toPlainString(),param.getLat2().toPlainString());
            w.between(BiIndexData::getLng,param.getLng1().toPlainString(),param.getLng2().toPlainString());
            param.setAreaCode(null);
            log.info("自定义区域选择");
        }else if(StringUtils.hasText(param.getAreaCode())){
            // 根据 省市区 查询所有指标数据
            SysArea sysArea = sysAreaService.getOne(new LambdaQueryWrapper<SysArea>().eq(SysArea::getAreaCode, param.getAreaCode()));
            districtName = sysArea.getName();
            w.eq(BiIndexData::getCountryName, districtName);
            log.info("开始计算区域选择："+districtName);
        }else{
            throw new ServiceException(9, "areaCode字段或坐标不能为空");
        }

        Long startTime = System.currentTimeMillis();
        JSONObject result = new JSONObject();
        //处理前端筛选的指标，进行过滤
        List<Long> indexList = param.getIndexList();
        if (CollectionUtil.isNotEmpty(indexList)) {
            w.in(BiIndexData::getTypeId,indexList);
        }

        CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
        List<BiIndexData> biIndexData = biIndexDataMapper.selectList(w);
        CurrentDataSourceContext.clearDataSourceType();
        if (CollectionUtil.isEmpty(biIndexData)) {
            return result;
        }
        log.info("所有指标数量："+biIndexData.size());
        // 将指标数据按照 经纬度分组
        HashMap<String, ArrayList<BiIndexData>> groupMap = new HashMap<>();
        for (BiIndexData i : biIndexData) {
            String lng = i.getLng().substring(0,10); // 114.235796
            String lat = i.getLat().substring(0,9); //   30.451186
            String key = lng + "," + lat;
            ArrayList<BiIndexData> list = groupMap.get(key);
            if (list == null) {
                list = new ArrayList<>();
                list.add(i);
                groupMap.put(key,list);
            }else{
                list.add(i);
            }
        }
        log.info("分组后网格数量："+groupMap.size());
        // 遍历某个经纬度下的所有指标，并按照权重计算分值
        ArrayList<JSONObject> clcaulatedArray = new ArrayList();
        HashMap<Long, BiIndexType> typeMap = new HashMap<>();
        biIndexTypeService.list().forEach(t -> typeMap.put(t.getId(),t));
        for (String key : groupMap.keySet()) {
            ArrayList<BiIndexData> list = groupMap.get(key);

            //如果一个网格内有多个相同类型的指标则去重
            HashMap<Long, BiIndexData> distinctMap = new HashMap<>();
            for (BiIndexData dd : list) {
                distinctMap.put(dd.getTypeId(), dd);
            }
            list = new ArrayList<>(distinctMap.values());


            JSONArray indexScoreList = new JSONArray();
            JSONArray indexSumList = new JSONArray();
            //先计算单个指标的分值
            for (BiIndexData d : list) {
                BiIndexType type = typeMap.get(d.getTypeId());
                double maxValue = type.getMaxValue().doubleValue();
                double minValue = type.getMinValue().doubleValue();
                if(minValue < 0){
                    minValue = 0;
                }
                double p = (maxValue-minValue)/10;
                double v = Double.parseDouble(d.getValue());
                double score = ((v - minValue) / p ) * 10;
                JSONObject element = new JSONObject();
                element.put("id",d.getTypeId());
                element.put("name",type.getName());
                element.put("value",new BigDecimal(score).setScale(2,4));
                indexScoreList.add(element);

                JSONObject element2 = new JSONObject();
                element2.put("name",type.getName());
                element2.put("value",new BigDecimal(d.getValue()).setScale(3,4));
                indexSumList.add(element);
            }
            //按照权重计算总分值
            BigDecimal score = this.calcScoreByIndustryWeight(indexScoreList, param.getThemeId());
            BiIndexData delegate = list.get(0);
            JSONObject element = new JSONObject();

            //点位居中
            String location = key;
            JSONArray objects = this.biIndexDataService.changeMultipolygon(delegate.getMultipolygon());
            if(objects!=null && objects.size()>3){
                JSONArray p1 = objects.getJSONArray(0);
                JSONArray p2 = objects.getJSONArray(2);
                double lng0 = (p1.getDouble(0)+p2.getDouble(0))/2;
                double lat0 = (p1.getDouble(1)+p2.getDouble(1))/2;
                location=""+lng0+","+lat0;
            }

            element.put("location", location);
            element.put("score", score);
            element.put("multipolygon",delegate.getMultipolygon());

            element.put("indexScoreList",groupIndexScore(indexScoreList));
            element.put("indexSumList",indexSumList);
            clcaulatedArray.add(element);
        }
        log.info("处理分值排名前10的数据");
        // 按照分值排序并生成序号，取前10个数据，经纬度逆编码为地址
        clcaulatedArray.sort((e1,e2)->{
            return e2.getBigDecimal("score").compareTo(e1.getBigDecimal("score"));
        });
        ArrayList<JSONObject> rows = new ArrayList<>();
        for (int i = 0; i < clcaulatedArray.size()&&i<10;i++) {
            JSONObject element = clcaulatedArray.get(i);
            element.put("seq", i + 1);
            String location = element.getString("location");
            String address = this.requestAmapRegeocodeAddress(location);
            if(address.contains(districtName)){
                address = address.split(districtName)[1];
            }
            element.put("name", address);
            // 计算同类主题近一年真实成交数据
            BigDecimal lng = new BigDecimal(location.split(",")[0]);
            BigDecimal lat = new BigDecimal(location.split(",")[1]);
            JSONArray themeStoreOrderSum = queryThemeStoreOrderSum(param.getThemeId(),lng,lat,1);
            element.put("lng", lng);
            element.put("lat", lat);
            element.put("themeId", param.getThemeId());
            element.put("themeDataSum",themeStoreOrderSum );
            //cdx
            JSONArray indexScoreList = element.getJSONArray("indexScoreList");
            if (indexScoreList != null && indexScoreList.size() > 0) {
                JSONObject maxScoreObject = (JSONObject)indexScoreList.get(0);
                Iterator var23 = indexScoreList.iterator();

                while(var23.hasNext()) {
                    Object obj = var23.next();
                    JSONObject el = (JSONObject)obj;
                    if (el.getBigDecimal("value").compareTo(maxScoreObject.getBigDecimal("value")) > 0) {
                        maxScoreObject = el;
                    }
                }

                element.put("tag", maxScoreObject.getString("name") + "分值高");
            }
            rows.add(element);
        }
        // 按照单个点查询格式返回
        result.put("rows", rows);
        // 保存到session会话中，可以提供对比操作
        request.getSession().setAttribute("FIND_POINT",rows);

        // 整理网格数据
        log.info("开始整理网格数据");
        JSONArray pointArray = new JSONArray();
        List<String> colorLevel = GridColorUtils.getColorLevel(param.getColor());
        double max = clcaulatedArray.stream().mapToDouble(
                el -> el.getBigDecimal("score").doubleValue()
        ).max().orElse(0);
        double min = clcaulatedArray.stream().mapToDouble(
                el -> el.getBigDecimal("score").doubleValue()
        ).min().orElse(0);
        for (JSONObject d : clcaulatedArray) {
            JSONObject point = new JSONObject();
            point.put("multipolygonArray",biIndexDataService.changeMultipolygon(d.getString("multipolygon")));
            point.put("value", d.getBigDecimal("score"));
            String score = d.getBigDecimal("score").setScale(3, 4).toPlainString();
            String colorByValue = GridColorUtils.getColorByValue(colorLevel, max, min, score);
            point.put("color", colorByValue);
            pointArray.add(point);
        }
        JSONObject grid = new JSONObject();
        grid.put("list",pointArray);
        grid.put("colorLevel", colorLevel);
        grid.put("valueRange", GridColorUtils.getValueRange(colorLevel,max,min));
        result.put("grid", grid);
        log.info("区域选择分析全部处理完成，用时："+(System.currentTimeMillis()-startTime));
        return result;
    }

    /**
     * 给指标得分进行分组，按照指标大类取平均值
     * @return
     */
    private JSONArray groupIndexScore(JSONArray indexScoreList){
        JSONArray groupedScoreList = new JSONArray();
        if (indexScoreList == null || indexScoreList.size() == 0) {
            return groupedScoreList;
        }
        HashMap<String, BigDecimal> scoreMap = new HashMap<>();
        List<Long> typeList = new ArrayList<>();
        for (Object o : indexScoreList) {
            JSONObject element = (JSONObject)o;
            typeList.add(element.getLong("id"));
            scoreMap.put(element.getString("name"), element.getBigDecimal("value"));
        }

        QueryParam queryParam = new QueryParam();
        queryParam.setIndexTypeIds(typeList);
        UserIndexTree userIndexTree = indexTypeManageService.indexTypeTree(queryParam);
        //将第二层的children设置为null
        if(CollectionUtil.isNotEmpty(userIndexTree.getChildren())){
            List<UserIndexTree> tList = userIndexTree.getChildren();
            for (UserIndexTree t : tList) {
                BigDecimal score = BigDecimal.ZERO;
                List<UserIndexTree> subList = t.getChildren();
                for (UserIndexTree tt : subList) {
                    BigDecimal bigDecimal = scoreMap.get(tt.getTitle());
                    if (bigDecimal != null) {
                        score = score.add(bigDecimal);
                    }
                }
                //取平均值
                score = score.divide(new BigDecimal(subList.size()), 2, 4);
                JSONObject scoreObject = new JSONObject();
                scoreObject.put("id", t.getKey());
                scoreObject.put("name", t.getTitle());
                scoreObject.put("value",score);
                groupedScoreList.add(scoreObject);
            }
        }
        return groupedScoreList;
    }

    public Object indexTypeWeightTree(){
        List<IndexTypeWeight> weightList = indexTypeWeightService.list(new LambdaQueryWrapper<IndexTypeWeight>().select(IndexTypeWeight::getTypeId));
        List<Long> typeList = weightList.stream().map(e->e.getTypeId()).distinct().collect(Collectors.toList());
        QueryParam queryParam = new QueryParam();
        queryParam.setIndexTypeIds(typeList);
        UserIndexTree userIndexTree = indexTypeManageService.indexTypeTree(queryParam);
        //将第二层的children设置为null
        if(CollectionUtil.isNotEmpty(userIndexTree.getChildren())){
            List<UserIndexTree> list = userIndexTree.getChildren();
            for (UserIndexTree t : list) {
                List<UserIndexTree> subList = t.getChildren();
                for (UserIndexTree tt : subList) {
                    tt.setChildren(null);
                }
            }
        }
        return userIndexTree;
    }


    /**
     * 智能选址详细报告查询
     * @param param
     * @return
     */
    public JSONObject queryDetailReport(PointAnalysisParam param) {
        String cacheKey = MD5.create().digestHex(JSONObject.toJSONString(param));
        JSONObject cacheObject = baseDataRecordCache.get(cacheKey);
        if (cacheObject != null) {
            return cacheObject;
        }
        if (param.getDistance() == null) {
            param.setDistance(1);
        }
        param.setColor("DETAIL_REPORT");
        JSONObject point = this.findPoint(param);
        if (point == null || point.get("rows") == null
                || point.getJSONArray("rows").size()==0) {
            return point;
        }
        JSONObject result = point.getJSONArray("rows").getJSONObject(0);
        BigDecimal lng = result.getBigDecimal("lng");
        BigDecimal lat = result.getBigDecimal("lat");
        Long industryId = param.getThemeId(); //主题编号（industryId）
        Integer distance = param.getDistance(); //统计范围

        //1、 周边同类型主题数量，最多显示2个主题店铺及撒点
        log.info("处理周边同类型主题数量");
        JSONArray themeDataSum = result.getJSONArray("themeDataSum");
        if (themeDataSum == null) {
            themeDataSum = new JSONArray();
            result.put("themeDataSum", themeDataSum);
        }
        //2、 周边基建数量及撒点 （住宅区、写字楼、产业园、工业大楼/大厦）
        log.info("处理周边基建数量及撒点（住宅区、写字楼、产业园、工业大楼/大厦）");
        {
            //查询clickhouse数据库的bi_poi_data表
            List<String> subTagList = Arrays.asList("住宅区","写字楼","产业园区","工业大楼","工业大厦");
            String[] points = DistanceHelper.getNearbyDistance(lng,lat, distance);
            LambdaQueryWrapper<BiPoiData> wrapper2 = new LambdaQueryWrapper<>();
            wrapper2.select(BiPoiData::getName, BiPoiData::getLng, BiPoiData::getLat, BiPoiData::getSubTag);
            wrapper2.in(BiPoiData::getSubTag, subTagList);
            wrapper2.between(BiPoiData::getLng, Double.parseDouble(points[0]), Double.parseDouble(points[1]));
            wrapper2.between(BiPoiData::getLat, Double.parseDouble(points[2]), Double.parseDouble(points[3]));
            CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
            List<BiPoiData> poiDataList = biPoiDataMapper.selectList(wrapper2);
            List<BiPoiData> poiDataListFilter = new ArrayList<>();
            CurrentDataSourceContext.clearDataSourceType();
            for (BiPoiData b : poiDataList) {
                //判断店铺的位置半径是否符合N公里条件
                double d = DistanceHelper.getDistince(DistanceHelper.parseDouble(b.getLng()),DistanceHelper.parseDouble(b.getLat()),
                        lng.doubleValue(),lat.doubleValue());
                if(d > distance){
                    continue;
                }
                poiDataListFilter.add(b);
            }
            HashMap<String, List<BiPoiData>> countMap = new HashMap<>();
            for (BiPoiData b : poiDataListFilter) {
                List<BiPoiData> subList = countMap.get(b.getSubTag());
                if (subList == null) {
                    subList = new ArrayList<>();
                }
                subList.add(b);
                countMap.put(b.getSubTag(), subList);
            }
            JSONArray infrastructureDataSum = new JSONArray();
            for (String s : subTagList) {
                JSONObject p1 = new JSONObject();
                if(s.equals("工业大楼")){
                    p1.put("name", "工业大楼/大厦");
                    int t1 = countMap.containsKey("工业大楼")?countMap.get("工业大楼").size():0;
                    int t2 = countMap.containsKey("工业大厦")?countMap.get("工业大厦").size():0;
                    p1.put("total", t1+t2);
                    p1.put("list",countMap.get(s));
                    infrastructureDataSum.add(p1);
                    break;
                }else{
                    p1.put("name", s);
                    p1.put("total", countMap.containsKey(s)?countMap.get(s).size():0);
                    p1.put("list",countMap.get(s));
                    infrastructureDataSum.add(p1);
                }
            }
            result.put("infrastructureDataSum", infrastructureDataSum);
            result.put("infrastructureTotal", infrastructureDataSum.stream().mapToInt(el->((JSONObject)el).getInteger("total")).sum());
//            result.put("infrastructureList", poiDataListFilter);
            log.info("周边基建数量:"+poiDataListFilter.size());
        }
        //3、 周边业态数量及撒点（餐饮美食、酒店住宿、科教文化、医疗保健、休闲娱乐）
        log.info("处理周边业态数量及撒点（餐饮美食、酒店住宿、科教文化、医疗保健、休闲娱乐）");
        {
            //查询clickhouse数据库的bi_poi_data表
            List<String> tagList = Arrays.asList("餐饮美食","酒店住宿","科教文化","医疗保健","休闲娱乐");
            String[] points = DistanceHelper.getNearbyDistance(lng,lat, distance);
            LambdaQueryWrapper<BiPoiData> wrapper2 = new LambdaQueryWrapper<>();
            wrapper2.select(BiPoiData::getName, BiPoiData::getLng, BiPoiData::getLat, BiPoiData::getTag);
            wrapper2.in(BiPoiData::getTag, tagList);
            wrapper2.between(BiPoiData::getLng, Double.parseDouble(points[0]), Double.parseDouble(points[1]));
            wrapper2.between(BiPoiData::getLat, Double.parseDouble(points[2]), Double.parseDouble(points[3]));
            CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
            List<BiPoiData> poiDataList = biPoiDataMapper.selectList(wrapper2);
            List<BiPoiData> poiDataListFilter = new ArrayList<>();
            CurrentDataSourceContext.clearDataSourceType();
            for (BiPoiData b : poiDataList) {
                //判断店铺的位置半径是否符合N公里条件
                double d = DistanceHelper.getDistince(DistanceHelper.parseDouble(b.getLng()),DistanceHelper.parseDouble(b.getLat()),
                        lng.doubleValue(),lat.doubleValue());
                if(d > distance){
                    continue;
                }
                poiDataListFilter.add(b);
            }
            HashMap<String, List<BiPoiData>> countMap = new HashMap<>();
            for (BiPoiData b : poiDataListFilter) {
                List<BiPoiData> subList = countMap.get(b.getTag());
                if (subList == null) {
                    subList = new ArrayList<>();
                }
                subList.add(b);
                countMap.put(b.getTag(), subList);
            }
            JSONArray businessTypeDataSum = new JSONArray();
            for (String s : tagList) {
                JSONObject p1 = new JSONObject();
                p1.put("name", s);
                p1.put("total", countMap.containsKey(s)?countMap.get(s).size():0);
                p1.put("list", countMap.get(s));
                businessTypeDataSum.add(p1);
            }
            result.put("businessTypeDataSum", businessTypeDataSum);
            result.put("businessTypeTotal", businessTypeDataSum.stream().mapToInt(el->((JSONObject)el).getInteger("total")).sum());
//            result.put("businessTypeList", poiDataListFilter);
            log.info("周边业态数量:"+poiDataListFilter.size());
        }

        //4、 周边交通数量及撒点（公交站、地铁、长途客运站、机场港口）
        log.info("处理周边交通数量及撒点（公交站、地铁、长途客运站、机场港口）");
        {
            //查询clickhouse数据库的bi_poi_data表
            List<String> subTagList = Arrays.asList("公交车站","地铁站","长途汽车站","飞机场","港口码头");
            String[] points = DistanceHelper.getNearbyDistance(lng,lat, distance);
            LambdaQueryWrapper<BiPoiData> wrapper2 = new LambdaQueryWrapper<>();
            wrapper2.select(BiPoiData::getName, BiPoiData::getLng, BiPoiData::getLat, BiPoiData::getSubTag);
            wrapper2.in(BiPoiData::getSubTag, subTagList);
            wrapper2.between(BiPoiData::getLng, Double.parseDouble(points[0]), Double.parseDouble(points[1]));
            wrapper2.between(BiPoiData::getLat, Double.parseDouble(points[2]), Double.parseDouble(points[3]));
            CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
            List<BiPoiData> poiDataList = biPoiDataMapper.selectList(wrapper2);
            List<BiPoiData> poiDataListFilter = new ArrayList<>();
            CurrentDataSourceContext.clearDataSourceType();
            for (BiPoiData b : poiDataList) {
                //判断店铺的位置半径是否符合N公里条件
                double d = DistanceHelper.getDistince(DistanceHelper.parseDouble(b.getLng()),DistanceHelper.parseDouble(b.getLat()),
                        lng.doubleValue(),lat.doubleValue());
                if(d > distance){
                    continue;
                }
                poiDataListFilter.add(b);
            }
            HashMap<String, List<BiPoiData>> countMap = new HashMap<>();
            for (BiPoiData b : poiDataListFilter) {
                List<BiPoiData> subList = countMap.get(b.getSubTag());
                if (subList == null) {
                    subList = new ArrayList<>();
                }
                subList.add(b);
                countMap.put(b.getSubTag(), subList);
            }
            JSONArray trafficDataSum = new JSONArray();
            for (String s : subTagList) {
                JSONObject p1 = new JSONObject();
                if(s.equals("飞机场")){
                    p1.put("name", "机场/港口");
                    int t1 = countMap.containsKey("飞机场")?countMap.get("飞机场").size():0;
                    int t2 = countMap.containsKey("港口码头")?countMap.get("港口码头").size():0;
                    p1.put("total", t1+t2);
                    List<BiPoiData> list1 = countMap.get("港口码头");
                    List<BiPoiData> list2 = countMap.get("飞机场");
                    if (list1 == null) {
                        list1 = new ArrayList<>();
                    }
                    if (list2 == null) {
                        list2 = new ArrayList<>();
                    }
                    list1.addAll(list2);
                    p1.put("list",list1);
                    trafficDataSum.add(p1);
                    break;
                }else{
                    p1.put("name", s);
                    if(s.equals("地铁站")){
                        int t = 0;
                        for (BiPoiData b : poiDataListFilter) {
                            if (b.getName().contains("(地铁站)")) {
                                t++;
                            }
                        }
                        p1.put("total", t);
                    }else{
                        p1.put("total", countMap.containsKey(s)?countMap.get(s).size():0);
                    }
                    p1.put("list",countMap.get(s));
                    trafficDataSum.add(p1);
                }
            }
            result.put("trafficDataSum", trafficDataSum);
            result.put("trafficTotal", trafficDataSum.stream().mapToInt(el->((JSONObject)el).getInteger("total")).sum());
//            result.put("trafficList", poiDataListFilter);
            log.info("周边交通数量:"+poiDataListFilter.size());
        }
        baseDataRecordCache.put(cacheKey,result);
        return result;
    }

    @Override
    public UserIndexTree getIndustryWeightTree(PointAnalysisParam param) {
        JSONObject industryWeightCacheMap = getIndustryWeightCacheMap(param.getThemeId(),false);
        //查询指标名称，重新组装返回报文
        JSONObject result = new JSONObject();
        if (industryWeightCacheMap != null) {
            HashMap<String, BigDecimal> valueMap = new HashMap<>();
            Set<String> typeSet = industryWeightCacheMap.keySet();
            List<BiIndexType> indexTypeList = biIndexTypeService.findByIds(new ArrayList(typeSet));
            for (BiIndexType t : indexTypeList) {
                valueMap.put(t.getName(),industryWeightCacheMap.getBigDecimal(String.valueOf(t.getId())));
            }
            HttpSession session = HttpServletUtil.getRequest().getSession();
            JSONObject sessionWeightMap = (JSONObject)session.getAttribute("INDUSTRY_" + param.getThemeId());
            if (sessionWeightMap == null) {
                sessionWeightMap = new JSONObject();
            }
            log.info("sessionWeightMap:"+sessionWeightMap.toJSONString());
            List<Long> typeList = indexTypeList.stream().map(e->e.getId()).distinct().collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(typeList)) {
                log.info("typeList:"+typeList);
                QueryParam queryParam = new QueryParam();
                queryParam.setIndexTypeIds(typeList);
                UserIndexTree userIndexTree = indexTypeManageService.indexTypeTree(queryParam);
                //将第二层的children设置为null,并回写指标权重值
                if(CollectionUtil.isNotEmpty(userIndexTree.getChildren())){
                    List<UserIndexTree> list = userIndexTree.getChildren();
                    for (UserIndexTree t : list) {
                        log.info("UserIndexTree="+t.getTitle());
                        List<UserIndexTree> subList = t.getChildren();
                        if (subList == null) {
                            continue;
                        }
                        for (UserIndexTree tt : subList) {
                            tt.setIsSelect("true");
                            BigDecimal value = sessionWeightMap.getBigDecimal(String.valueOf(tt.getKey()));
                            if (value == null) {
                                value = valueMap.get(tt.getTitle());
                                if(sessionWeightMap.size()>0){
                                    tt.setIsSelect("false");
                                }
                            }
                            tt.setWeightValue(value);
                            tt.setChildren(null);
                        }
                    }
                }
                return userIndexTree;
            }
        }

        return new UserIndexTree();
    }
}
